package com.centerserver;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.List;
import java.util.Map;

class ProcessMonitorEndRequestThread extends Thread {

	private Socket mSocket;
	private DatabaseManager mDatabaseManager;
//	private Map<String, InetAddress> mInetAddrMap;
	private Map<String, List<String>> mMonitorListMap;
	
	public ProcessMonitorEndRequestThread(
			Socket socket, 
			DatabaseManager databaseManager,
//			Map<String, InetAddress> inetAddrMap,
			Map<String, List<String>> monitorListMap) {
		mSocket = socket;
		mDatabaseManager = databaseManager;
//		mInetAddrMap = inetAddrMap;
		mMonitorListMap = monitorListMap;
	}

	@Override
	public void run() {
		
		try {
			InputStream inputStream = mSocket.getInputStream();
			byte[] btMonitorIntent = new byte[4];
			inputStream.read(btMonitorIntent, 0, 4);
			
			String monitorIntent = new String(btMonitorIntent, "ISO-8859-1");
			if(monitorIntent.equals("QUIT")) {
				
				int capLen = inputStream.read();
				byte[] btCapName = new byte[capLen];
				inputStream.read(btCapName, 0, capLen);
				
				String capName = new String(btCapName, "ISO-8859-1");
				String monitorIp = ((InetSocketAddress)mSocket.getRemoteSocketAddress())
									.getAddress()
									.getHostAddress();
				
				mMonitorListMap.get(capName).remove(monitorIp);
				return;
			}
			
			List<String> availableCaptureEndList = mDatabaseManager.getAllAvailableCaptureEndName();
			System.out.println("availableCaptureEndList size: " + availableCaptureEndList.size());
			
			OutputStream outputStream = mSocket.getOutputStream();
			
			// the max length of capture end name is 255 
			int maxBufLen = (availableCaptureEndList.size()<<8); 
			byte[] availableCaptureEnd = new byte[maxBufLen];
			int bufLen = 0;
			
			for(int i=0; i<availableCaptureEndList.size(); i++) {
				
				byte[] tmp = availableCaptureEndList.get(i).getBytes("ISO-8859-1");
				availableCaptureEnd[bufLen] = (byte) tmp.length;
				System.arraycopy(tmp, 0, availableCaptureEnd, ++bufLen, tmp.length);
				
				bufLen += tmp.length;
			}
			
			/*
			 * send the information of available capture end to monitor end
			 */
			outputStream.write(bufLen/256); // bufLen/256 < 255
			outputStream.write(bufLen%256);
			outputStream.write(availableCaptureEnd, 0, bufLen);
			System.out.println("Debug: send available capture end");
			
			/*
			 *  get the choice of monitor end
			 */
			int captureEndNameLen = inputStream.read();
			
			// monitor end doesn't choose one capture end
			if( -1 == captureEndNameLen ) {
				mSocket.close();
				System.out.println(" monitor end doesn't choose one capture end");
				return;
			}
			
			System.out.println("Debug: Len:" + captureEndNameLen);
			byte[] sendCaptureEndName = new byte[captureEndNameLen];
			
			inputStream.read(sendCaptureEndName, 0, captureEndNameLen);
			
			System.out.println("receive client's choice");
			System.out.println(new String(sendCaptureEndName, 0, captureEndNameLen, "ISO-8859-1"));
			
			/*
			 * add the IP address of the monitor end to list
			 */
			String capEndName = new String(sendCaptureEndName, "ISO-8859-1");
			String romoteIpAddr = ((InetSocketAddress)mSocket.getRemoteSocketAddress())
									.getAddress()
									.getHostAddress();
			System.out.println("Debug: remote ip address: " + romoteIpAddr);
			mMonitorListMap.get(capEndName).add(romoteIpAddr);
			
//			/*
//			 * send the multicast address to monitor end
//			 */
//			String ipAddress = mDatabaseManager.getIpAddressByCaptureEndName(
//					new String(sendCaptureEndName, 0, captureEndNameLen, "ISO-8859-1"));
//			
//			String multicastAddr = mInetAddrMap.get(ipAddress).getHostAddress();
//			int addrLen =  multicastAddr.length();
//			
//			System.out.println("Debug: multiAddr: " + multicastAddr);
//			
//			outputStream.write(addrLen);
//			outputStream.write(multicastAddr.getBytes("ISO-8859-1"));
			
			/**
			 * send SPS & PPS
			 */
			byte[] sps = null;
			byte[] pps = null;
			try {
				sps = mDatabaseManager.getSpsByCaptureEndName(capEndName).getBytes("ISO-8859-1");
				pps = mDatabaseManager.getPpsByCaptureEndName(capEndName).getBytes("ISO-8859-1");
			} catch (UnsupportedEncodingException e1) {
				System.out.println("UnsupportedEncodingException in SendSpsPps");
				e1.printStackTrace();
			}
			
			// send SPS & PPS to monitor end
			try {
				outputStream.write(sps.length);
				outputStream.write(sps);
				outputStream.write(pps.length);
				outputStream.write(pps);
			} catch (IOException e) {
				System.out.println("IOException in SendSpsPps");
				e.printStackTrace();
			}

		} catch (Exception e) {
			System.out.println("Exception in ProcessMonitorEndRequest");
			e.printStackTrace();

		} finally {

			try {
				mSocket.close();
			} catch (IOException e) {
				System.out.println("IOException in ProcessMonitorEndRequest");
				e.printStackTrace();
			}
		}
	}
}
